using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARFoundation;

[RequireComponent(typeof(ARFaceManager))]
public class DisplayFaceInfo : MonoBehaviour
{
    [SerializeField] Text m_FaceInfoText;

    public Text faceInfoText
    {
        get { return m_FaceInfoText; }
        set { m_FaceInfoText = value; }
    }

    ARFaceManager m_FaceManager;
    private int minIndex;
    
    private int[] PointIndexs = {10655, 9265, 9218, 10796, 8940, 10609, 9103};
    // 下面的颜色是调试用的，因为大智忘了上面那些数字对应是那些位置了 /(ㄒoㄒ)/~~
    private Color[] Colors = {Color.black, Color.white, Color.blue, Color.gray, Color.green, Color.red, Color.yellow};
    private Dictionary<int, GameObject> BallMap = new Dictionary<int, GameObject>();
    private int _verticeCount;


    void Awake()
    {
        m_FaceManager = GetComponent<ARFaceManager>();

        
        m_FaceManager.facesChanged += delegate(ARFacesChangedEventArgs args)
        {
            if (args.added.Count > 0)
            {
                var face = args.added[0];

                for (var i = 0; i < PointIndexs.Length; i++)
                {
                    var index = PointIndexs[i];
                    var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    go.transform.localScale = Vector3.one * 0.01f;

                    var pos = face.vertices[index];
                    // 设置父物体为人脸，这样物体会跟随人脸移动
                    go.transform.SetParent(face.transform);
                    go.transform.localPosition = pos;
                    go.GetComponent<Renderer>().material.color = Colors[i];

                    BallMap[index] = go;
                }
            }
            
            // 更新点的位置，added的时候可能mesh还不准确，顶点位置有可能更新
            if (args.updated.Count > 0)
            {
                var face = args.updated[0];
            
                foreach (var index in PointIndexs)
                {
                    var pos = face.vertices[index];
                    var go = BallMap[index];
                    go.transform.localPosition = pos;
                }
            }
        };
    }

    void Update()
    {
        if (m_FaceManager.subsystem != null && faceInfoText != null)
        {
            faceInfoText.text = $"Supported number of tracked faces: {m_FaceManager.supportedFaceCount}\n" +
                                $"Max number of faces to track: {m_FaceManager.maximumFaceCount}\n" +
                                $"Number of tracked faces: {m_FaceManager.trackables.count}";
            
            // 这样可以在UI上看到顶点的数量
            faceInfoText.text += "\n当前脸部Mesh的顶点数为：" + _verticeCount;
            
            // 这样可以在UI上看到顶点的索引
            faceInfoText.text += "\n离点击位置最近的顶点索引是：" + _verticeCount;
        }

        // ！！！下面是添加的代码
        if (Input.GetMouseButtonUp(0))
        {
            var camera = GetComponent<ARSessionOrigin>().camera;
            var ray = camera.ScreenPointToRay(Input.mousePosition);

            if (Physics.Raycast(ray, out var hit, 1000))
            {
                var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                go.transform.localScale = Vector3.one * 0.01f;
                // 设置父物体为人脸，这样物体会跟随人脸移动
                go.transform.SetParent(hit.transform);
                go.transform.position = hit.point;

                var face = hit.transform.GetComponent<ARFace>();
                // 需要在类中创建一个int类型的私有成员
                _verticeCount = face.vertices.Length;
                
                
                var min = float.MaxValue;
                // 需要在类中创建一个int类型的私有成员
                minIndex = -1;
                for (var index = 0; index < face.vertices.Length; index++)
                {
                    var v = face.vertices[index];
                    var local = hit.transform.InverseTransformPoint(hit.point);
                    
                    // 使用sqrMagnitude可以减少一次开方计算，结果一样，性能更好
                    var distance = (v - local).sqrMagnitude;
                    if (distance < min)
                    {
                        minIndex = index;
                        min = distance;
                    }
                }

            }
        }
    }
}